﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the LGPL License, Version 3.0. See License.txt in the project root for license information.
// Website: https://admin.blazor.zone

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using PetaPoco;
using PetaPoco.Providers;
using System;
using System.Collections.Generic;

namespace BlazorAdmin.Services.DbService
{
    /// <summary>
    /// 数据库管理类
    /// </summary>
    internal class PetaPocoService : IPetaPoco
    {
        private readonly IConfiguration configuration;
        private readonly ILogger<PetaPocoService> logger;
        private readonly IWebHostEnvironment webHost;
        private readonly IDatabaseBuildConfiguration option;

        public PetaPocoService(IConfiguration configuration, ILogger<PetaPocoService> logger, IWebHostEnvironment webHost)
        {
            this.configuration = configuration;
            this.webHost = webHost;

            // 添加数据库连接设置
            option = CreateOption("BaMgmtDb", "SqlServer");
        }

        private IDatabaseBuildConfiguration CreateOption(string connName, string provider)
        {
            var option = DatabaseConfiguration.Build();
            option.UsingDefaultMapper<PetaPocoConventionMapper>();
            option.UsingConnectionString(configuration.GetConnectionString(connName));

            switch (provider.ToLower())
            {
                case "mysql":
                    option.UsingProvider<MySqlDatabaseProvider>();
                    break;
                case "sqlserver":
                    option.UsingProvider<SqlServerDatabaseProvider>();
                    break;
                case "oracle":
                    option.UsingProvider<OracleDatabaseProvider>();
                    break;
            }

            return option;
        }

        /// <summary>
        /// 创建 IDatabase 实例方法
        /// </summary>
        /// <param name="connectionName">连接字符串键值</param>
        /// <param name="keepAlive"></param>
        /// <returns></returns>
        public IDatabase Create(bool keepAlive = false)
        {
            Database db = null;

            try
            {
                db = new Database(option) { KeepConnectionAlive = keepAlive };
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return db;

            /*db.ExceptionThrown += (sender, e) =>
            {
                var message = e.Exception.Format(new NameValueCollection()
                {
                    [nameof(db.LastCommand)] = db.LastCommand,
                    [nameof(db.LastArgs)] = string.Join(",", db.LastArgs)
                });
                logger.LogError(e.Exception, "{Message}", message);
            };
            if (webHost.IsDevelopment())
            {
                db.CommandExecuted += (sender, args) =>
                {
                    var parameters = new StringBuilder();
                    foreach (DbParameter p in args.Command.Parameters)
                    {
                        parameters.AppendFormat("{0}: {1}  ", p.ParameterName, p.Value);
                    }
                    logger.LogInformation("{CommandText}", args.Command.CommandText);
                    logger.LogInformation("{CommandArgs}", parameters.ToString());
                };
            };*/

            //return db;
        }

        public IDatabase Create(string connName, bool keepAlive = false)
        {
            return new Database(option) { KeepConnectionAlive = keepAlive };
        }
    }

    public static class IDatabaseExtension
    {
        public static void LogAsync(this IDatabase db, string action)
        {
            /*ThreadPool.QueueUserWorkItem(state =>
            {
                var script = db.LastCommand ?? db.LastSQL ?? string.Empty;
                var ignoreTables = new List<string>() { "DBLogs", "Exceptions", "LoginLogs", "Logs", "Traces" };

                if (!Regex.IsMatch(script, @"Insert\s+Into\s+" + $"\"({string.Join("|", ignoreTables)})\"", RegexOptions.Multiline | RegexOptions.IgnoreCase))
                    db.InsertAsync(new DBLog() { Action = action, SQL = script, LogTime = DateTime.Now });
            });*/
        }
    }
}